<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // 第一题

    /* call 和 apply 的区别是什么,哪个性能更好一些 ?*/
    // 1.call 和 apply 都是Function.prototype的方法,而每一个函数/方法都可以作为Function的实例,所以调用call和applay方法
    // 2.call 和 applay 可以立即执行函数,并且改变函数中this的指向
    // 3.call传递的参数是第一个是this的指向,后面的是传递的实参,而apply只有两个参数,第一个是this指向的对象,第二个参数是一个数组
    // 4. bind 也可以改变this的指向,最大的不同是他不会立即执行
    // fn.call(obj,10,20,30);
    // fn.apply(obj,[10,20,30]);
    // call和applay 都有传改变原来this指向的参数的时候,后面的参数(apply应该指的是数组里面的元素了)在3个或3个以内,两者的性能
    // 是一样的,3个以上的话apply的性能比call的性能要低
    // 如果是传递有个数组并且不能用到es6 '...'的语法的话就用apply


    /*
    let arr = [10,20,30],
    obj = {};
    function fn (x,y,z) {
    console.log(x,y,z);
    }
    fn.apply(obj,arr); // 10 20 30
    fn.call(obj,arr);//  [10, 20, 30] undefined undefined 
    fn.call(obj,...arr); //10 20 30 => 基于ES6的展开运算符也可以实现把数组中的每一项依次传递给函数

    */

    /* 
    性能测试的小代码 
    注意：自己实现的性能测试(只供参考):任何的代码的性能测试都是和测试的环境有关系的,例如CPU、 内存、 GPU等电脑当前性能不会有相同的情况,不同浏览器也会导致性能上的不同
    */

    /* 
    1. 这种方法只能精确到毫秒
    let t1 = new Date();
    for(let i = 0; i < 10; i ++) {

    }
    console.log(new Date() - t1); 
    */

    // 2. console.time 和 console.timeEnd
    /*
    console.time('A');
    for (let i = 0; i < 10; i++) {

    }
    console.timeEnd('A'); //A: 0.006103515625ms
    */

    // 3. console.profil 和 console.profileEnd 需要安装火狐浏览器 和 fireBug

  /*   console.profile('A');
    for (let i = 0; i < 10; i++) {

    }
    console.profileEnd('A'); 
  */
   
    // 第二题

    // 实现(5).add(3).minus(2),使其输出结果为:6
  /* 
     Number.prototype.add = function(num) {
      return this + num;
    }
    Number.prototype.minus = function(num) {
      return this - num;
    }
    console.log((5).add(3).minus(2));
 */
    //老师的答案
 /* ~function() {
   //=>每一个方法执行完,都要返回Number这个类的实例,这样才可以继续调取Number类原型中的方法(链式写法)
   //注意:this是不能像变脸一样赋值,我们只能改变this的指向,但是我们不能改变this的值,否则就会报错
    function check(n) {
      n = Number(n);
      return isNaN(n) ? 0 : n;
    }
    function add(n) {
      n = check(n);
      return this + n;
    }
    function minus(n) {
      n = check(n);
      return this - n;
    }
    let arr = [add,minus];
    ['add','minus'].forEach(item => {
      Number.prototype[item] = eval(item);
    });
 }();
console.log((5).add(3).minus(2)); */

//第三题
/* 箭头函数与普通的函数(function)的区别是什么?
  构造函数(function)可以使用new 生成实例, 那么箭头函数可以吗? 为什么? 
*/
// 知识补充: 
//    回调函数: 把一个函数B作为实参传递给另一个函数A,函数A在执行的时候,可以把传递进来的函数B去执行(执行N次,可传值,可改this)
/* 
 * 箭头函数和普通函数的区别
    1.  箭头函数语法上比普通函数更加简洁(ES6中每一种函数都可以使用形参默认值和剩余运算符)
    2.  箭头函数没有自己的this,它里面的this是继承函数所处上下文中的this(使用call/apply等任何方式都无法改变this的指向)
    3.  箭头函数中没有arguments(类数组),只能基于...arg获取传递的参数集合(数组)
    4.  构造函数不能被new执行(因为：箭头函数没有this也没有prototype)
 */

/*
  demo  
    document.body.onclick = ()=>{
      //=> this:window 不是当前操作的body了
  }
    document.body.onclick = function () {
      //=> this:body
    arr.sort(function(a,b) {
      //=>this:window 回调函数中的this一般都是window
      return a - b;
    })
    arr.sort((a,b) => {
      //=>this: body
      return a - b;
    })
  }
 */
  </script>
</body>
</html>